﻿using Furion.CMS.Application.Dto;
using Furion.CMS.Core;
using Furion.CMS.Core.Base;
using Furion.CMS.Domain;
using Furion.DatabaseAccessor;
using Furion.DistributedIDGenerator;
using Furion.FriendlyException;
using Mapster;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Furion.CMS.Application
{
    /// <summary>
    /// 数据字典应用服务
    /// </summary>
    [DisplayName("DictionaryManager")]
    public class DataDictionaryAppService : BaseApplication
    {
        private readonly IRepository<DataDictionary> _dictionaryRepository;
        private readonly IRepository<DataDictionaryCategory> _categoryRepository;
        private readonly IDistributedIDGenerator _idGenerator;

        public DataDictionaryAppService(IRepository<DataDictionary> dictionaryRepository,
            IRepository<DataDictionaryCategory> categoryRepository,
            IDistributedIDGenerator idGenerator)
        {
            _dictionaryRepository = dictionaryRepository;
            _categoryRepository = categoryRepository;
            _idGenerator = idGenerator;
        }

        /// <summary>
        /// 获取数据字典类别
        /// </summary>
        /// <returns></returns>
        public List<DataDictionaryCategoryDto> GetCategorys()
        {
            return _categoryRepository.AsQueryable(false)
                .OrderBy(o => o.SortNumber)
                .ThenByDescending(o => o.CreatedTime)
                .Adapt<List<DataDictionaryCategoryDto>>();
        }

        /// <summary>
        /// 数据字典分页查询
        /// </summary>
        /// <param name="index"></param>
        /// <param name="limit"></param>
        /// <param name="filter"></param>
        /// <param name="sort"></param>
        /// <returns></returns>
        [HttpPost]
        public PagingList<DataDictionaryDto> GetPagedList([ApiSeat(ApiSeats.ActionStart)] int index, [ApiSeat(ApiSeats.ActionStart)] int limit,
            [FromQuery] DataDictionaryFilter filter,
            [FromBody] DataDictionarySort sort = default)
        {
            var query = _dictionaryRepository.AsQueryable(false)
                .Where(filter.GetFilterExpression())
                .OrderBy(o => o.SortNumber)
                .ThenByDescending(o => o.CreatedTime);
            // 排序之后再进行分页处理
            var pageResult = new PagingList<DataDictionaryDto> { Current = index, PageSize = limit, Total = query.Count() };

            // 排序与分页处理
            pageResult.List = query.AsSortQuery(sort)
                .AsPagedQuery(index, limit)
                .Adapt<List<DataDictionaryDto>>();

            return pageResult;
        }

        /// <summary>
        /// 获取数据字典详情
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        [SecurityDefine]
        public DataDictionaryDetailDto GetDetail(string key)
        {
            var query = _dictionaryRepository.AsQueryable(false)
                    .Where(t => t.DataKey == key);

            if (!query.Any()) throw Oops.Oh($"未能找到 {key} 的详情数据");

            var dto = query.Include(i => i.Category)
                .FirstOrDefault()
                .Adapt<DataDictionaryDetailDto>();
            return dto;
        }

        /// <summary>
        /// 获取数据类别字典详情
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [SecurityDefine]
        public DataDictionaryCategoryDetailDto GetCategoryDetail([RouteConstraint(":guid")] Guid id)
        {
            var entity = _categoryRepository.AsQueryable(false)
                 .Where(t => t.Id == id)
                 .FirstOrDefault();

            if (entity == null) throw Oops.Oh($"未能找到Id为 {id} 的详情数据");

            return entity.Adapt<DataDictionaryCategoryDetailDto>();
        }

        /// <summary>
        /// 创建类别
        /// </summary>
        /// <param name="input"></param>
        [SecurityDefine]
        public void CreateCategory([FromBody] InputDataDictionaryCategoryDto input)
        {
            var entity = input.Adapt<DataDictionaryCategory>();
            entity.Id = Guid.Parse(_idGenerator.Create().ToString());
            _categoryRepository.Insert(entity);
        }

        /// <summary>
        /// 创建数据字典项
        /// </summary>
        /// <param name="input"></param>
        [SecurityDefine]
        public void Create([FromBody] CreateDataDictionaryDto input)
        {
            var entity = input.Adapt<DataDictionary>();
            var isAny = _dictionaryRepository.AsQueryable(false).Where(t => t.DataKey == input.DataKey).Any();

            if (isAny)
                throw Oops.Oh($"{input.DataKey} 已存在,请重新填写!");

            _dictionaryRepository.Insert(entity);
        }

        /// <summary>
        /// 更新字典类别
        /// </summary>
        /// <param name="id"></param>
        /// <param name="dto"></param>
        [SecurityDefine]
        public void UpdateCategory([RouteConstraint(":guid"), ApiSeat(ApiSeats.ActionStart)] Guid id, [FromBody] InputDataDictionaryCategoryDto dto)
        {
            var input = dto.Adapt<DataDictionaryCategory>();
            var history = _categoryRepository.AsQueryable(false).FirstOrDefault(t => t.Id == id);

            if (history == null) throw Oops.Oh($"未能找到ID为 {id} 的数据字典类别数据");

            var update = history.AsMergeObject(input, "Id", "CreatedTime");

            _categoryRepository.Update(update);
        }

        /// <summary>
        /// 更新字典项数据
        /// </summary>
        /// <param name="key"></param>
        /// <param name="dictionaryDto"></param>
        [SecurityDefine]
        public void Update(string key, [FromBody] UpdateDataDictionaryDto dictionaryDto)
        {
            var history = _dictionaryRepository.AsQueryable(false).FirstOrDefault(t => t.DataKey == key);
            if (history == null) throw Oops.Oh($"未能找到 {key} 的数据");

            var input = dictionaryDto.Adapt<DataDictionary>();

            var update = history.AsMergeObject(input, "DataKey", "CreatedTime", "SortNumber");
            update.UpdatedTime = DateTimeOffset.UtcNow;
            _dictionaryRepository.Update(update, true);
        }

        /// <summary>
        /// 删除一个或多个字典项
        /// </summary>
        /// <param name="keys"></param>
        [SecurityDefine]
        public void Delete([FromBody] string[] keys)
        {
            var deletes = _dictionaryRepository.AsQueryable(false).Where(t => keys.Contains(t.DataKey)).ToList();
            _dictionaryRepository.Delete(deletes);
        }

        /// <summary>
        /// 删除字典类别
        /// </summary>
        /// <param name="id"></param>
        [UnitOfWork]
        [SecurityDefine]
        public void DeleteCategory([RouteConstraint(":guid"), ApiSeat(ApiSeats.ActionStart)] Guid id)
        {
            var deleteItem = _categoryRepository.AsQueryable(false).FirstOrDefault(t => t.Id == id);

            if (deleteItem == null) throw Oops.Oh($"未能找到ID为 {id} 的数据字典类别数据");

            var deleteSubList = _dictionaryRepository.AsQueryable(false).Where(t => t.CategoryId == id).ToList();
            _dictionaryRepository.DeleteNow(deleteSubList);
            _categoryRepository.Delete(deleteItem);
        }
    }
}
